#ifndef __M_CONSUMER_H__
#define __M_CONSUMER_H__
#include"../mqcommon/mq_helper.hpp"
#include"../mqcommon/mq_logger.hpp"
#include"../mqcommon/mq_msg.pb.h"
#include<string>
#include<iostream>
#include<unordered_map>
#include<memory>
#include<vector>
#include<functional>
namespace bitmq{
    using ConsumerCallBack=std::function<void(const std::string&,const bitmq::BasicProperties*bp,const std::string&)>;
    //消费者信息结构
    struct Consumer{
        using ptr=std::shared_ptr<Consumer>;
        std::string _tag;//消费者标识
        std::string _qname;//消费者订阅的队列名male
        bool _auto_ack;//是否自动应答
        ConsumerCallBack _callback;//消费者回调函数
        Consumer(const std::string&tag,const std::string& qname,bool auto_ack,const ConsumerCallBack& cb)
        :_tag(tag)
        ,_qname(qname)
        ,_auto_ack(auto_ack)
        ,_callback(std::move(cb)){}
    };
    //以队列为单元的消费者管理
    class QueueConsumer{
        public:
        using ptr=std::shared_ptr<QueueConsumer>;
        QueueConsumer(const std::string&qname):_qname(qname),_rr_seq(0){}
        //添加一个消费者
        Consumer::ptr create(const std::string&tag,const std::string& qname,bool auto_ack,const ConsumerCallBack& cb)
        {
            //1、加锁
            std::unique_lock<std::mutex> lock(_mutex);
            //2、遍历是否重复  重复返回空
            for(auto&consumer:_consumers)
            {
                if(consumer->_tag==tag)
                {
                    return Consumer::ptr();
                }
            }
            //3、构造对象  添加到消费者管理结构
            auto consumer=std::make_shared<Consumer>(tag,qname,auto_ack,cb);//智能指针参数可以随便写，在编写代码时不会报错。编译时报错
            _consumers.push_back(consumer);
            //4、返回
            return consumer;
        }
        //移除一个消费者
        void remove(const std::string&tag)
        {
            std::unique_lock<std::mutex> lock(_mutex);

            //遍历删除
            for(auto it=_consumers.begin();it!=_consumers.end();it++)
            {
                if((*it)->_tag==tag)
                {
                    _consumers.erase(it);
                    return;
                }
            }
            return ;
        }
        //选择一个的消费者，进行消费
        Consumer::ptr choose()
        {
            //加锁
            std::unique_lock<std::mutex> lock(_mutex);
            if(_consumers.size()==0)
            {
                return Consumer::ptr();
            }
            //计算
            int idx=_rr_seq%_consumers.size();
            //轮询序号++
            _rr_seq++;
            //返回
            return _consumers[idx];
        }
        //判断消费者是否为空
        bool empty()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _consumers.size()==0;
        }
        //判断指定消费者是否存在
        bool exists(const std::string&tag)
        {
            std::unique_lock<std::mutex> lock(_mutex);

            //遍历删除
            for(auto it=_consumers.begin();it!=_consumers.end();it++)
            {
                if((*it)->_tag==tag)
                {
                    return true; 
                }
            }
            return false;
        }
        
        //清除消费者
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _consumers.clear();
            _rr_seq=0;
        }
        private:
        std::string _qname;//队列名称
        std::mutex _mutex;//保护线程安全
        uint64_t _rr_seq;//RR轮询序号
        std::vector<Consumer::ptr> _consumers;//消费者管理结构
    };

    //向外提供统一的接口
    class ConsumerManager
    {
        public:
        using ptr=std::shared_ptr<ConsumerManager>;
        ConsumerManager(){}
        //初始化消费者队列
        void initQueueConsumer(const std::string&qname)
        {
            //加锁
            std::unique_lock<std::mutex> lock(_mutex);
            //判断重复
            auto it=_cmanager.find(qname);
            if(it!=_cmanager.end())
            {
                //DLOG("已经初始化，不需要重复！");
                return;
            }

            //构造对象  添加
            auto qconsumer=std::make_shared<QueueConsumer>(qname);
            _cmanager.insert(std::make_pair(qname,qconsumer));
            
        }
        //移除消费者队列
        void destroyQueueConsumer(const std::string&qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _cmanager.erase(qname);
        }
        //创建一个消费者，并返回消费者
        Consumer::ptr creater(const std::string&tag,const std::string& qname,bool auto_ack,const ConsumerCallBack& cb)
        {
            QueueConsumer::ptr qcptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it=_cmanager.find(qname);
                if(it==_cmanager.end())
                {
                    DLOG("没找到，消费者管理句柄！%s",qname.c_str());
                    return Consumer::ptr();
                }
                qcptr=it->second;
            }
            return qcptr->create(tag,qname,auto_ack,cb);
            
        }
        //移除一个消费者
        void remove(const std::string&tag,const std::string&qname)
        {
            QueueConsumer::ptr qcptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it=_cmanager.find(qname);
                if(it==_cmanager.end())
                {
                    DLOG("没找到，消费者管理句柄！%s",qname.c_str());
                    return;
                }
                qcptr=it->second;
            }
            qcptr->remove(tag);
        }
        //选择一个消费者消费
        Consumer::ptr choose(const std::string&qname)
        {
            QueueConsumer::ptr qcptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it=_cmanager.find(qname);
                if(it==_cmanager.end())
                {
                    DLOG("没找到，消费者管理句柄！%s",qname.c_str());
                    return Consumer::ptr();
                }
                qcptr=it->second;
            }
            return qcptr->choose();
        }
        //判断消费者队列是否为空
        bool empty(const std::string&qname)
        {
            QueueConsumer::ptr qcptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it=_cmanager.find(qname);
                if(it==_cmanager.end())
                {
                    DLOG("没找到，消费者管理句柄！%s",qname.c_str());
                    return false;
                }
                qcptr=it->second;
            }
            return qcptr->empty();
        }
        //判断指定消费者是否存在
        bool exists(const std::string&tag,const std::string&qname)
        {
            QueueConsumer::ptr qcptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it=_cmanager.find(qname);
                if(it==_cmanager.end())
                {
                    DLOG("没找到，消费者管理句柄！%s",qname.c_str());
                    return false;
                }
                qcptr=it->second;
            }

            return qcptr->exists(tag);
        }
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _cmanager.clear();
        }
        private:
        std::mutex _mutex;
        std::unordered_map<std::string,QueueConsumer::ptr> _cmanager;//队列名 &  消费者管理句柄
    };
}
#endif